iT邦幫忙

2026 iThome 鐵人賽

DAY 2
0
Modern Web

教練看不到的那六天|從 FIT 檔到 3D 軌跡,馬拉松訓練資料 Dashboard系列 第 2

Day 2|跑者的資料地圖:我的汗水都流去哪了

  • 分享至 

  • xImage
  •  

昨天提到我們的目標是建立一個 dashboard,第一步不是寫程式,是先來討論個問題:

我的訓練資料,現在到底在哪裡?

不盤不知道盤了嚇一跳—自己的日常訓練,資料居然分散在四處(真的是四個地方哈哈)不互通的地方,資料格式也相去甚遠。今天就來畫這張資料地圖,順便幫每個來源打一個「機器可讀性」的分數,因為之後要把它們全部撈進同一個地方,越難讀的,之後的篇幅也就會越多。


來源一:Garmin—看資料沒問題,問題是資料出不來

其實單看跑步的話,Garmin Connect 本身已經很夠用。距離、配速、心率、步頻、垂直振幅,連觸地時間都有,圖表也畫得很漂亮。以量來說它是壓倒性的第一名—一場全馬是一萬兩千多筆逐秒紀錄,這不是一般記事本可以攤開來看的資料格式。

所以它的問題不是沒有想看的資訊,而是只能在它家看

我要做的是把跑步、重訓、體重、課表放在同一個畫面裡對照—Garmin Connect 再漂亮,它也不知道我昨天練了腿、這週體重掉了多少、教練這週開了什麼。要統整四方資訊,資料就得離開 Garmin 的雲端,進到我的系統。而「離開」這件事,就得跟 Garmin 的 API 打交道—官方 API 不是隨便就申請得到的(這個之後會提)。

而且就算拿到了,摘要 API 給你的跟 app 裡看到的也是兩回事:

{
  "type": "track_running",
  "start": "2026-07-21 19:01:23",
  "distance_m": 5000.0,
  "pace": "6:17/km",
  "avg_hr": 143.0,
  "max_hr": 157.0
}

平均值、最大值,就這樣。想要「每一秒的心率」還原一場比賽?那就需要去取得原始的 FIT 檔—一個二進位格式,打開來是一堆看不懂的 bytes(Day 4–5 會提及)。

機器可讀性:B+。資料很結構化,但拿到手之前要先過 API 認證這關,拿到之後還有二進位解析這關。


來源二:體重機—資料就飄在空中,只差主動去取得

家中的小米體重機,官方的操作流程是:站上去 → 開 Zepp app → 資料上傳雲端 → 在 app 查閱。

但自己後來發現一件有趣的事:體重機根本沒在管你有沒有開 app。你站上去的那一刻,它就用藍牙 BLE 對外廣播體重和阻抗,廣播完就結束了,存不存資料都無所謂。

換句話說,資料不是只能在 App 和體重機螢幕上查看—每天量體重時,它其實都在家裡的空氣中免費放送,只是缺少一位知心人。所以就寫了個腳本當那個聽的人(Day 6 會提及)。

目前聽到的紀錄長這樣:

日期時間 體重 (kg) 阻抗 (Ω) 備註
2026-07-21 00:17 73.15 446 BLE 直讀

機器可讀性:A 自己聽的話,體重資料格式固定。走官方 app 反而分數會下降,因為還要跟雲端 API 打交道。


來源三:重訓紀錄—手稿式紀錄快速方便,但也是機器的惡夢

這是最有「人味」的一個來源,也是比較需要思考怎麼轉換資料的部分。

如果有用 Garmin 手錶的人可能很有感:Garmin Connect 明明確實可以記重訓,錶上有肌力訓練模式可以選擇,也會自動數次數。自己前期也有嘗試使用過。但對自己來說它記不下真正想紀錄的東西:

重訓紀錄是自己在組間休息時用手機打的,發展到現在已經長出一套自己的速記語法:

  • 🚀 = 該重量進步
  • 🔥 = 該組接近或到力竭
  • 8+4 @35 = 力竭後降重續做(drop set),35 公斤做 8 下力竭、降重後續 4 下

實際一筆紀錄長這樣:

啞鈴胸推斜板|12;12🚀,8🔥🔥🔥,6+6|35 降20

這一筆裡藏著的資訊是:35 公斤第一組做滿 12 下而且比上次進步、第三組力竭後降重續做、力竭的程度有分級。組數次數 Garmin 記得下,但「三個火焰🔥 」跟「上次同重量只做到 10 下」這種品質註記,它沒有欄位—而對重訓來說,這些註記才是下次課表怎麼調的依據。

自己能看得懂,但對機器來說這是一串謎語:分號和逗號各是什麼意思?🔥 出現三次跟一次差在哪?「降20」是重量還是次數?

而這套語法不是設計出來的,是經驗紀錄下來的—它隨著我的訓練習慣慢慢演化,充滿了只有當事人才懂的縮寫。Day 7–8 要處理的就是這個:怎麼把一套活的、手寫的語法,變成資料庫裡乾淨的欄位,又不用讓自己在組間休息時填寫訓練表單。

機器可讀性:D。但它是所有來源裡唯一「完全屬於自己」的資料—沒有 API、沒有雲端、沒有授權問題。


來源四:教練的課表—存在於 LINE 的記事本

跑班教練開課表的方式非常自然:

「這週四 1000 三趟,組間休兩分半,配速抓 1:36 秒/400公尺。」

教練固定會把課表貼在 LINE 記事本裡,照配速分組列出每組各自的課表—但終究是一則自然文字,沒有真正的欄位。有時候教練會視上課當下的狀況(今天狀態、天氣、場地),臨時把課表加碼或減碼,這種調整比較臨時需要自己另外文字紀錄。它是四個來源裡唯一變動性較高的—你不能 parse 一則 LINE 記事本裡的自由格式文字,更不能 parse 一句臨場喊出來的話。

但它偏偏是整個系統裡最重要的資料。因為「教練開的」是計畫,其他三個來源記的是「實際發生的」—沒有計畫,就沒有『達成率』這個概念,執行與復盤這一段比較難即時觀測。Day 15 的監督執行計畫,比的就是這兩邊。

機器可讀性:F。變動性高,各種內容也需要多加解析。


整張地圖攤開來

來源 格式 更新頻率 誰產生 機器可讀性
Garmin JSON / FIT 二進位 每次跑步 手錶 B+
體重機 BLE 廣播 13 bytes 每天早上 體重機 A
重訓紀錄 自創語法的文字 每次重訓 自己 D
教練課表 LINE 記事本文字 / 臨場口頭調整 每週 教練 F

問題顯而易見可讀性越高的,越不重要;越重要的,越難讀,體重機的 13 bytes 工整且乾淨,但它只是體重;教練的課表決定整週訓練,但它格式比較難解析。

這就是接下來的施工順序:先從好撈的撈起,一路往難的打,最後把最難的那個也收進來。

明天會從 Garmin 的 API 先開始打交道,明天見啦~


上一篇
Day 1|以終為始:一條會變色的馬拉松軌跡
下一篇
Day 3|取得 Garmin 資料:官方 API vs garminconnect 套件實測
系列文
教練看不到的那六天|從 FIT 檔到 3D 軌跡,馬拉松訓練資料 Dashboard6
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言